import ServerUtil
from nodeinfo import Info
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import copy

# Done Testing
# It gives the total height and width of the whole network tree to be drawn
def getTreeHeightAndWidth(nodeDict):
    height = 1
    nodeDictCopy = copy.copy(nodeDict)
    childList = ServerUtil.findServerAsParent(nodeDict)
    width = 0
    treeHW = {}
    while(nodeDictCopy):
        nWidth = len(childList)
        if nWidth > width:
            width = nWidth
        toRemoveNodes = []
        toRemoveNodes = childList
        childList = ServerUtil.getNextChildNodes(childList, nodeDict)
        nodeDictCopy = ServerUtil.removeNodefromDict(toRemoveNodes, nodeDictCopy)
        height = height + 1
    treeHW.setdefault('height', height)
    treeHW.setdefault('width', width)
    return treeHW

# Optimize this method
def setPositionForNodes(childList, serverW, serverH, posDict):
    noOfChild = len(childList)
    widthFactor = 0.0
    if not noOfChild == 0:
        widthFactor = serverH / (serverW/noOfChild)
    height = serverH - 1
    if (noOfChild == 1):
        posDict.setdefault(childList[0], (serverW, height))
    if (noOfChild == 2):
        changeRatio = serverW/2
        posDict.setdefault(childList[0], (serverW - widthFactor, height))
        posDict.setdefault(childList[1], (serverW + widthFactor, height))
    if (noOfChild == 3):
        changeRatio = serverW/3       
        posDict.setdefault(childList[0], (serverW, height))
        posDict.setdefault(childList[1], (serverW - widthFactor, height))
        posDict.setdefault(childList[2], (serverW + widthFactor, height))
    if (noOfChild == 4):
        changeRatio = serverW/4
        posDict.setdefault(childList[0], (serverW - (serverW/2), height))
        posDict.setdefault(childList[1], (serverW + (serverW/2), height))
        posDict.setdefault(childList[2], (serverW - (serverW/4), height))
        posDict.setdefault(childList[3], (serverW + (serverW/4), height))
    if (noOfChild == 5):
        posDict.setdefault(childList[0], (serverW, height))
        posDict.setdefault(childList[1], (serverW - (serverW/2), height))
        posDict.setdefault(childList[2], (serverW + (serverW/2), height))
        posDict.setdefault(childList[3], (serverW - (serverW/4), height))
        posDict.setdefault(childList[4], (serverW + (serverW/4), height))
    return posDict
            
def getPositionForNodes(nodeDict):
    treeHW = getTreeHeightAndWidth(nodeDict)
    height = treeHW.get('height')
    width = treeHW.get('width')
    posDict = {}
    # Adding Server's position to the posDict(Dictionary)
    posDict.setdefault('server',(width/2 , height))
    childList = ServerUtil.findServerAsParent(nodeDict)
    posDict = setPositionForNodes(childList, posDict.get('server')[0], posDict.get('server')[1], posDict)
    for i in range(0, int(height) - 2):
        for i in range(0, len(childList)):
            listOfChild = nodeDict.get(childList[i]).getChild()
            serverWidth = posDict.get(childList[i])[0]
            serverHeight = posDict.get(childList[i])[1]
            posDict = setPositionForNodes(listOfChild, serverWidth, serverHeight, posDict)
        childList = ServerUtil.getNextChildNodes(childList, nodeDict)
    return posDict    

# It draws the original tree of the network
def drawBaseTree(nodeDict):
    nodeList = []
    nodeLabel = {}
    edgeList = []
    edgeLabel = {}
    for key in nodeDict:
        nInfo = Info()
        nodeObj = nodeDict.get(key)
        nodeList.append(key)
        nodeLabel.setdefault(key, key)
        if not nodeObj.getName() == 'server':
            edgeList.append((nodeObj.getParent(), nodeObj.getName()))
            edgeLabel.setdefault((nodeObj.getParent(),nodeObj.getName()), 'D : ' +str(nodeObj.getDelay()) +'\nB : ' + str(nodeObj.getUBandWidth()))
    nodeList.append('server')
    nodeLabel.setdefault('server', 'server')
    serverChild = ServerUtil.findServerAsParent(nodeDict)
    for val in serverChild:
        edgeList.append(('server', val))
        edgeLabel.setdefault(('server',val), 'D : ' +str((nodeDict.get(val)).getDelay()) +'\nB : ' + str((nodeDict.get(val)).getUBandWidth()))
    posDict = getPositionForNodes(nodeDict)
    G = nx.house_graph()
    nx.draw_networkx_nodes(G, posDict, node_size=270, nodelist=nodeList, node_color='b')
    nx.draw_networkx_edges(G, posDict, alpha=0.75,width=2,edgelist=edgeList)
    nx.draw_networkx_labels(G, posDict, labels=nodeLabel)
    nx.draw_networkx_edge_labels(G, posDict, edge_labels=edgeLabel)
    plt.axis('off')
    plt.show()
    #print nodeList
    #print nodeLabel
    #print edgeList
    #print edgeLabel
    #nodeDict = operate.addNodeToDatabase()
    


